package com.pine.dbant.common.plugin.meta;

import com.pine.dbant.common.model.ConnectionInfo;
import com.pine.dbant.common.plugin.JdbcException;
import com.pine.dbant.common.store.CacheStore;
import com.pine.sunflower.core.LifeCycledAdapter;
import com.pine.sunflower.core.plugin.Configuration;
import com.pine.sunflower.core.utils.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xiaoyuan
 * @create 2021/12/6 10:58
 **/
@Slf4j
public abstract class AbstractJdbcMetadataAnalysis extends LifeCycledAdapter implements JdbcMetadataAnalysis, JdbcMetadataAnalysisConfig {


    /**
     * 获取的元数据信息
     */
    protected DatabaseMetaData dbMetaData;

    protected Connection connection;
    /**
     * 元数据分析拦截器
     */
    protected MetaAnalysisFilter metaAnalysisFilter;
    /**
     * 表类型白名单
     */
    protected String[] whiteListTableTypes = new String[]{"TABLE", "VIEW"};
    private ConnectionInfo connectionInfo;
    private Configuration configuration;
    private CacheStore cacheStore;
    /**
     * 数据库
     */
    //返回数据库中可用的目录名称时，该目录名称随后存储在名为TABLE_CAT的列下
    protected static final String TABLE_CAT = "TABLE_CAT";
    protected static final String TABLE_CATALOG = "TABLE_CATALOG";
    protected static final String TABLE_SCHEM = "TABLE_SCHEM";
    protected static final String TABLE_NAME = "TABLE_NAME";
    protected static final String TABLE_TYPE = "TABLE_TYPE";
    protected static final String REMARKS = "REMARKS";
    protected static final String COLUMN_NAME = "COLUMN_NAME";
    protected static final String DATA_TYPE = "DATA_TYPE";
    protected static final String TYPE_NAME = "TYPE_NAME";
    protected static final String COLUMN_SIZE = "COLUMN_SIZE";
    protected static final String BUFFER_LENGTH = "BUFFER_LENGTH";
    protected static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
    protected static final String NUM_PREC_RADIX = "NUM_PREC_RADIX";
    protected static final String NULLABLE = "NULLABLE";
    protected static final String COLUMN_DEF = "COLUMN_DEF";
    protected static final String SQL_DATA_TYPE = "SQL_DATA_TYPE";
    protected static final String SQL_DATETIME_SUB = "SQL_DATETIME_SUB";
    protected static final String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH";
    protected static final String ORDINAL_POSITION = "ORDINAL_POSITION";
    protected static final String IS_NULLABLE = "IS_NULLABLE";
    protected static final String SCOPE_CATALOG = "SCOPE_CATALOG";
    protected static final String SCOPE_SCHEMA = "SCOPE_SCHEMA";
    protected static final String SCOPE_TABLE = "SCOPE_TABLE";
    protected static final String SOURCE_DATA_TYPE = "SOURCE_DATA_TYPE";
    protected static final String TYPE = "TYPE";
    protected static final String NON_UNIQUE = "NON_UNIQUE";
    protected static final String INDEX_NAME = "INDEX_NAME";
    protected static final String KEY_SEQ = "KEY_SEQ";
    protected static final String PK_NAME = "PK_NAME";
    /**
     * 一般数据库的判断自增的属性名
     */
    protected static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";

    private  final Map<String, QueryMetadataFunction> QUERY_METADATA_FUNCTION_MAP = new HashMap<>();


    @Override
    public AbstractJdbcMetadataAnalysis connectionInfo(ConnectionInfo connectionInfo) {
        this.connectionInfo = connectionInfo;
        return this;
    }

    @Override
    public AbstractJdbcMetadataAnalysis configuration(Configuration configuration) {
        this.configuration = configuration;
        return this;
    }

    @Override
    public AbstractJdbcMetadataAnalysis connection(Connection connection) {
        this.connection = connection;
        try {
            databaseMetaData(connection.getMetaData());
        } catch (SQLException e) {
            throw new JdbcMetaAnalysisException(e.getMessage(), e);
        }
        return this;
    }


    public AbstractJdbcMetadataAnalysis databaseMetaData(DatabaseMetaData metaData) {
        this.dbMetaData = metaData;

        return this;
    }


    @Override
    public AbstractJdbcMetadataAnalysis filter(MetaAnalysisFilter filter) {
        this.metaAnalysisFilter = filter;
        return this;
    }

    @Override
    public AbstractJdbcMetadataAnalysis addFunction(List<QueryMetadataFunction> functions) {
        if (CollectionUtils.isEmpty(functions)) {
            throw new JdbcMetaAnalysisException("未添加查询元数据方法类");
        }
        functions.forEach(queryMetadataFunction -> QUERY_METADATA_FUNCTION_MAP.put(queryMetadataFunction.getType(), queryMetadataFunction));
        return this;
    }

    @Override
    public AbstractJdbcMetadataAnalysis addFunction(QueryMetadataFunction function) {
        QUERY_METADATA_FUNCTION_MAP.put(function.getType(), function);
        return this;
    }

    @Override
    public CacheStore getCacheStore() {
        return this.cacheStore;
    }

    @Override
    public AbstractJdbcMetadataAnalysis cacheStore(CacheStore cacheStore) {
        this.cacheStore = cacheStore;
        return this;
    }

    @Override
    public ConnectionInfo getConnectionInfo() {
        return this.connectionInfo;
    }

    @Override
    public Configuration getConfiguration() {
        return this.configuration;
    }

    @Override
    public MetaAnalysisFilter getMetaAnalysisFilter() {
        return this.metaAnalysisFilter;
    }

    @Override
    public List<QueryMetadataFunction> getFunctions() {
        return new ArrayList<>(QUERY_METADATA_FUNCTION_MAP.values());
    }

    @Override
    public Connection getConnection() {
        return this.connection;
    }

    @Override
    public QueryMetadataFunction getFunction(String type) {
        return QUERY_METADATA_FUNCTION_MAP.get(type);
    }

        @Override
    public Object queryMetadata(QueryMetadataParam queryMetadataParam) {
        QueryMetadataFunction queryMetadataFunction = QUERY_METADATA_FUNCTION_MAP.get(queryMetadataParam.getType());
        if (queryMetadataFunction == null) {
            throw new JdbcMetaAnalysisException(Strings.format("未发现该类型[{}]实现", queryMetadataParam.getType()));
        }
        try{
            return queryMetadataFunction.query(this, queryMetadataParam);
        }finally {
            stop();
        }

    }

    @Override
    public void doStop() {
        if (connection != null) {
            try {
                connection.close();
                connection = null;
            } catch (SQLException e) {
                throw new JdbcException("Unable to close a connection", e);
            }

        }
    }

    //    @Override
//    public List<MetadataNode> getcatalogs() {
//        Set<String> catalogs = Sets.newConcurrentHashSet();
//        List<MetadataNode> metadataNodes = new ArrayList<>();
//        try (ResultSet rs = dbMetaData.getCatalogs()) {
//            while (rs.next()) {
//                String catalog = rs.getString(TABLE_CAT);
//                if (StringUtils.isEmpty(catalog)) {
//                    log.warn("忽略为空的catalog");
//                    continue;
//                }
//                if (filterCatalog(catalog)) {
//                    log.warn("忽略在拦截器中过滤的catalog[{}]", catalog);
//                    continue;
//                }
//                catalogs.add(catalog);
//            }
//        } catch (SQLException e) {
//            log.error("获取该数据源的所有数据库catalog错误", e);
//            throw new JdbcMetaAnalysisException("获取该数据源的所有数据库catalog错误", e);
//        }
//        metadataNodes.addAll(catalogs.stream().map(dbName -> new DefaultMetadataNode()
////                .setTypeName(JdbcMetadataTreeView.DATABASE.getTypeName())
//                .setType(JdbcMetadataTreeView.DATABASE.getType())
////                .setLabel(dbName)
//                .addProperty("connId", this.connectionInfo.getId())).collect(Collectors.toList()));
//        return metadataNodes;
//    }
//
//
//    @Override
//    public List<MetadataNode> getMetadataNodes(String catalog) {
//
//        List<MetadataNode> metadataNodes = new ArrayList<>();
//        List<Table> tables = getTables(catalog, null, TableType.TABLE.name(), TableType.VIEW.name());
//        metadataNodes.addAll(tables.stream().map(table -> {
//            MetadataNode metadataNode = new DefaultMetadataNode();
//            metadataNode.addProperty("connId", this.connectionInfo.getId());
//            metadataNode.addProperty("dbName", catalog);
//          //  metadataNode.setLabel(table.getTableName());
//            metadataNode.setType(table.getTableType());
//          //  metadataNode.setTypeName(JdbcMetadataTreeView.TABLE.getTypeName());
//            if (table.getTableType().equals(TableType.VIEW.name())) {
//              //  metadataNode.setTypeName(JdbcMetadataTreeView.VIEW.getTypeName());
//            }
//            return metadataNode;
//        }).collect(Collectors.toList()));
//        return metadataNodes;
//    }
//

//
//    @Override
//    public Set<String> getSchemas(String catalog) {
//        Set<String> schemas = Sets.newConcurrentHashSet();
//        try (ResultSet rs = dbMetaData.getSchemas(catalog, null)) {
//            while (rs.next()) {
//                String schemaName = rs.getString(TABLE_SCHEM);
//                String catalogName = rs.getString(TABLE_CATALOG);
//                if (StringUtils.isEmpty(schemaName)) {
//                    log.warn("忽略为空的schema");
//                    continue;
//                }
//                if (shouldTableIgnore(catalogName, schemaName, null)) {
//                    log.warn("忽略在拦截器中过滤的[catalog:{},schema:{}]", catalogName, schemaName);
//                    continue;
//                }
//                schemas.add(schemaName);
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库{}下Schema错误", catalog, e);
//            throw new JdbcMetaAnalysisException(String.format("获取数据库[%s]下Schema错误", catalog), e);
//        }
//        return schemas;
//    }
//
//    @Override
//    public List<Table> getTables(String catalog, String schemaName, String... tableTypes) {
//        return buildTableInfo(catalog, schemaName, null, false);
//    }
//
//    private List<Table> buildTableInfo(String catalog, String schemaName, String tableName, boolean fetchDetail) {
//        List<Table> tables = new ArrayList<>();
//        if (shouldTableIgnore(catalog, schemaName, tableName)) {
//            log.warn("忽略拦截器中白名单的[catalog:{},schemaName:{},tableName:{}]", catalog, schemaName, tableName);
//            return tables;
//        }
//        try (ResultSet rs = dbMetaData.getTables(catalog, schemaName, StringUtils.isEmpty(tableName) ? null : tableName,
//                whiteListTableTypes)) {
//            while (rs.next()) {
//                Map<String, Object> map = map(rs);
//                String tbCatalog = rs.getString(TABLE_CAT);
//                String tbSchema = rs.getString(TABLE_SCHEM);
//                String tbName = rs.getString(TABLE_NAME);
//                if (shouldTableIgnore(tbCatalog, tbSchema, tbName)) {
//                    log.debug("catalog:{}, schema:{}, table:{} ignored by filter.", tbCatalog, tbSchema, tbName);
//                    continue;
//                }
//                // dbMetaData.getTables(catalog, schemaPattern, tablePattern)中：
//                // schemaPattern, tablePattern表示模糊匹配
//                // Jdk Doc: 一些DatabaseMetaData方法使用String模式的参数。 这些参数都有名称，如fooPattern。
//                // 在模式字符串中，“%”表示匹配0个或更多字符的任何子字符串，“_”表示匹配任何一个字符。
//                // 只返回与搜索模式匹配的元数据条目。 如果搜索模式参数设置为null ，则该参数的标准将从搜索中删除。
//                // 这种情况可能会查出其他schema或者其他表, 需要过滤
//                if (schemaName != null && !schemaName.equals(tbSchema)) {
//                    continue;
//                }
//                if (tableName != null && !tableName.equals(tbName)) {
//                    continue;
//                }
//                // 表类型
//                String tableType = rs.getString(TABLE_TYPE);
//                // 表备注
//                String remarks = rs.getString(REMARKS);
//                Table table = new Table();
//                table.setCatalogName(catalog);
//                table.setSchemaName(schemaName);
//                table.setTableComment(remarks);
//                table.setTableName(tbName.trim());
//                table.setTableType(tableType);
//                //获取表字段信息
//                table.setFields(fetchDetail ? buildFiled(catalog, schemaName, tbName) : null);
//                //获取序列键信息
////                table.setIndexes(fetchDetail ? buildIndexs(catalog, schemaName, tableName) : null);
//                tables.add(table);
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]->schema[{}]下的表信息错误", catalog, schemaName, e);
//            throw new JdbcMetaAnalysisException(String.format("获取数据库[%s]->schema[%s]下的表信息错误", catalog, schemaName), e);
//        }
//        return tables;
//    }
//
//
//    public Map<String, Object> map(ResultSet row) throws SQLException {
//        Map<String, Object> map = new Hashtable<>();
//        ResultSetMetaData metaData = row.getMetaData();
//        int count = metaData.getColumnCount();
//        for (int i = 1; i <= count; i++) {
//            String key = metaData.getColumnName(i);
//            Object value = row.getObject(i);
//            map.put(key, value == null ? "" : value);
//        }
//        return map;
//    }
//
//    protected List<Field> buildFiled(String catalog, String schemaName, String tableName) {
//        List<Field> columns = new ArrayList<>();
//        List<PrimaryKey> primaryKeys = getPrimaryKeys(catalog, schemaName, tableName);
//        try (ResultSet rs = dbMetaData.getColumns(catalog, schemaName, tableName, null)) {
//            while (rs.next()) {
//                // tableName中若带有下划线，例如C_2,则dbMetaData.getColumns会对表名模糊匹配，导致找出其他表如CA2表的字段
//                // 需要过滤
//                String realTableName = rs.getString(TABLE_NAME);
//                if (StringUtils.isNotEmpty(tableName) && !realTableName.equals(tableName)) {
//                    continue;
//                }
//                // 过滤schema中被模糊匹配到其他schema的字段
//                String realSchema = rs.getString(TABLE_SCHEM);
//                if (StringUtils.isNotBlank(schemaName) && !schemaName.equals(realSchema)) {
//                    continue;
//                }
//                int ordinalPosition = rs.getInt(ORDINAL_POSITION);
//                String columnName = rs.getString(COLUMN_NAME);
//                //String typeName = rs.getString(TYPE_NAME);
//                int jdbcType = rs.getInt(DATA_TYPE);
//                String comment = rs.getString(REMARKS);
//                String defaultValue = rs.getString(COLUMN_DEF);
//                int columnSize = rs.getInt(COLUMN_SIZE);
//                int decimalDigits = rs.getInt(DECIMAL_DIGITS);
//                boolean autoincrement = isColumnAutoincrement(rs);
//                boolean nullable = isColumnNullable(rs);
//
//                Field column = new Field();
//                column.setCatalogName(catalog);
//                column.setSchemaName(schemaName);
//                column.setTableName(tableName);
//                column.setOrdinalPosition(ordinalPosition);
//                column.setColumnName(columnName);
//                column.setJdbcType(jdbcType);
//                column.setFieldComment(comment);
//                column.setPrimaryKey(primaryKeys.stream().anyMatch(r -> r.getColumnName().trim().equalsIgnoreCase(columnName)));
//                column.setDefaultValue(defaultValue);
//                column.setSize(columnSize);
//                column.setDecimalDigits(decimalDigits);
//                column.setAutoincrement(autoincrement);
//                column.setNullable(nullable);
//                columns.add(column);
//            }
//        } catch (SQLException e) {
//            log.error("获取字段元数据信息错误[catalog:{},schema:{},table:{}]", catalog, schemaName, tableName, e);
//            throw new JdbcMetaAnalysisException(e.getMessage(), e);
//        }
//        return columns;
//    }
//
//
//    @Override
//    public List<PrimaryKey> getPrimaryKeys(String catalog, String schemaName, String tableName) {
//        List<PrimaryKey> primaryKeys = Lists.newArrayList();
//        try (ResultSet rs = dbMetaData.getPrimaryKeys(catalog, schemaName, tableName)) {
//            while (rs.next()) {
//                primaryKeys.add(new PrimaryKey(rs.getString(COLUMN_NAME), rs.getShort(KEY_SEQ), rs.getString(PK_NAME)));
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的表[{}]的主键信息错误", catalog, schemaName, tableName, e);
//            throw new JdbcMetaAnalysisException(e.getMessage(), e);
//        }
//        return primaryKeys;
//    }
//
//
//    protected List<Index> buildIndexs(String catalog, String schemaName, String tableName) {
//        List<Index> indices = Lists.newArrayList();
//        /**
//         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
//         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
//         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
//         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
//         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
//         */
//        try (ResultSet rs = dbMetaData.getIndexInfo(catalog, schemaName, tableName, false, false)) {
//            while (rs.next()) {
//                String tbCatalog = rs.getString(TABLE_CAT);
//                String tbSchema = rs.getString(TABLE_SCHEM);
//                String tbName = rs.getString(TABLE_NAME);
//                if (shouldTableIgnore(tbCatalog, tbSchema, tbName)) {
//                    log.debug("catalog:{}, schema:{}, table:{} ignored by filter.", tbCatalog, tbSchema, tbName);
//                    continue;
//                }
//                // 非唯一索引(Can
//                // index values
//                // be
//                // non-unique.
//                // false when
//                // TYPE is
//                // tableIndexStatistic
//                // )
//                short type = rs.getShort(TYPE);
//                if (type == 0) {
//                    continue;
//                }
//                boolean nonUnique = rs.getBoolean(NON_UNIQUE);
////                // 索引目录（可能为空）
////                String indexQualifier = rs.getString("INDEX_QUALIFIER");
//                // 索引的名称
//                String indexName = rs.getString(INDEX_NAME);
//                // 索引类型
//
//                // 在索引列顺序号
//                short ordinalPosition = rs.getShort(ORDINAL_POSITION);
//                // 列名
//                String columnName = rs.getString(COLUMN_NAME);
//
//                Index index = new Index();
//                index.setCatalogName(catalog);
//                index.setSchemaName(schemaName);
//                index.setTableName(tableName);
//               // index.setColumnNames(Lists.newArrayList(columnName));
//                index.setIndexType(type);
//                index.setIndexName(indexName);
//             //   index.setNonUnique(nonUnique);
//                index.setOrdinalPosition(ordinalPosition);
//                indices.add(index);
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的表[{}]的索引错误", catalog, schemaName, tableName, e);
//            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
//        }
//        return indices;
//    }
//
//
//    /**
//     * 判断该列是否允许包含空值
//     *
//     * @param columnMetaData 列的元数据，从DatabaseMetaData.getColumns得到
//     * @return 列是否可为空。若无法判断，则返回true
//     */
//    protected boolean isColumnNullable(ResultSet columnMetaData) {
//        try {
//            // ISO规则用来确定某一列的为空性。 YES---如果该参数可以包括空值; NO---如果参数不能包含空值
//            // 空字符串---如果参数为空性是未知的
//            String sNullable = columnMetaData.getString(IS_NULLABLE);
//            return "YES".equals(sNullable);
//        } catch (SQLException e) {
//            log.warn("【元数据获取】获取列nullable失败", e);
//        }
//        return true;
//    }
//
//
//    /**
//     * 判断该列是否自增
//     *
//     * @param columnMetaData 列的元数据，从DatabaseMetaData.getColumns得到
//     * @return 列是否自增。若无法判断，则返回false
//     */
//    protected boolean isColumnAutoincrement(ResultSet columnMetaData) {
//        try {
//            //  指示此列是否是自动递增 是---如果该列是自动递增 无---如果不是自动递增列 空字串---如果不能确定它是否
//            //  列是自动递增的参数是未知
//            String sAutoincrement = columnMetaData.getString(IS_AUTOINCREMENT);
//            return "YES".equals(sAutoincrement);
//        } catch (SQLException e) {
//            log.warn("【元数据获取】获取列autoincrement失败", e);
//        }
//        return false;
//    }
//
//    /**
//     * 表的元数据采集是否应该被忽略
//     *
//     * @param catalog   catalog
//     * @param schema    schema
//     * @param tableName 表名
//     * @return 该表应被忽略
//     */
//    private boolean shouldTableIgnore(String catalog, String schema, String tableName) {
//        return filterCatalog(catalog) || filterSchema(schema) || filterTable(tableName);
//    }
//
//
//    /**
//     * 过滤是否在白名单中的catalog
//     *
//     * @param catalog
//     * @return
//     */
//    protected boolean filterCatalog(String catalog) {
//        return this.metaAnalysisFilter.checkIgnoreCatalog(catalog);
//    }
//
//    /**
//     * 过滤是否在白名单中的schema
//     *
//     * @param schemaName schema名字
//     * @return
//     */
//    protected boolean filterSchema(String schemaName) {
//        return this.metaAnalysisFilter.checkIgnoreSchema(schemaName);
//    }
//
//    /**
//     * 过滤是否在白名单中的table
//     *
//     * @param tableName table名字
//     * @return
//     */
//    protected boolean filterTable(String tableName) {
//        return this.metaAnalysisFilter.checkIgnoreTableName(tableName);
//    }
//
//
//    @Override
//    public Table getTableDetail(String catalog, String schemaName, String tableName) {
//        List<Table> tables = buildTableInfo(catalog, schemaName, tableName, true);
//        if (CollectionUtils.isEmpty(tables)) {
//            throw new JdbcMetaAnalysisException(Strings.format("该表[{}]不存在", tableName));
//        }
//        return tables.get(0);
//    }
//
//    @Override
//    public List<Field> getField(String catalog, String schemaName, String tableName) {
//        return buildFiled(catalog, schemaName, tableName);
//    }
//
//    @Override
//    public List<Index> getIndexs(String catalog, String schemaName, String table) {
//        return buildIndexs(catalog, schemaName, table);
//    }
//
//    @Override
//    public List<ForeignKey> getForeignKeys(String catalog, String schemaName, String table) {
//        List<ForeignKey> indices = Lists.newArrayList();
//        /**
//         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
//         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
//         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
//         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
//         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
//         */
//        try (ResultSet rs = dbMetaData.getImportedKeys(catalog, schemaName, table)) {
//            ResultSetMetaData fkmd = rs.getMetaData();
//            while (rs.next()) {
//                for (int i = 1; i <= fkmd.getColumnCount(); i++) {
//                    System.out.println(fkmd.getColumnName(i) + "\t" + rs.getString(i));
//                }
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的表[{}]的外键信息错误", catalog, schemaName, table, e);
//            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
//        }
//        return indices;
//    }
//
//    @Override
//    public List<Produce> getProduces(String catalog, String schemaName) {
//        List<Produce> indices = Lists.newArrayList();
//        /**
//         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
//         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
//         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
//         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
//         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
//         */
//        try (ResultSet rs = dbMetaData.getProcedures(catalog, schemaName, null)) {
//            ResultSetMetaData fkmd = rs.getMetaData();
//            while (rs.next()) {
//                for (int i = 1; i <= fkmd.getColumnCount(); i++) {
//                    System.out.println(fkmd.getColumnName(i) + "\t" + rs.getString(i));
//                }
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的外键信息错误", catalog, schemaName, e);
//            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
//        }
//        return indices;
//    }
//
//    @Override
//    public List<Function> getFunctions(String catalog, String schemaName) {
//        List<Function> indices = Lists.newArrayList();
//        /**
//         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
//         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
//         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
//         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
//         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
//         */
//        try (ResultSet rs = dbMetaData.getFunctions(catalog, schemaName, null)) {
//            ResultSetMetaData fkmd = rs.getMetaData();
//            while (rs.next()) {
//                for (int i = 1; i <= fkmd.getColumnCount(); i++) {
//                    System.out.println(fkmd.getColumnName(i) + "\t" + rs.getString(i));
//                }
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的外键信息错误", catalog, schemaName, e);
//            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
//        }
//        return indices;
//    }
//
//    @Override
//    public List<Trigger> getTriggers(String catalog, String schemaName) {
//        List<Trigger> indices = Lists.newArrayList();
//        /**
//         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
//         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
//         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
//         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
//         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
//         */
//        try (ResultSet rs = dbMetaData.getFunctions(catalog, schemaName, null)) {
//            ResultSetMetaData fkmd = rs.getMetaData();
//            while (rs.next()) {
//                for (int i = 1; i <= fkmd.getColumnCount(); i++) {
//                    System.out.println(fkmd.getColumnName(i) + "\t" + rs.getString(i));
//                }
//            }
//        } catch (SQLException e) {
//            log.error("获取数据库[{}]下schema[{}]的外键信息错误", catalog, schemaName, e);
//            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
//        }
//        return indices;
//    }
//
//    @Override
//    public String buildDDL(String catalog, String schemaName, String tableName) {
//        String sql = "show create table `{}`.`{}`";
//        Map<String, Object> record = JdbcUtils.getSqlRunner(this.connection).selectOne(Strings.format(sql, catalog, tableName));
//        if (record == null || record.size() != 2) {
//            throw new JdbcMetaAnalysisException(Strings.format("获取表[{}]的DDL语句错误", tableName));
//        }
//        return String.valueOf(record.get("Create Table"));
//    }

//    @Override
//    public List<String> buildTableChangeSql(Table table) {
//        Table oldTable = getTableDetail(table.getCatalogName(), table.getSchemaName(), table.getKey());
//        if (oldTable == null) {
//            return Arrays.asList(buildCreateTableSql(table));
//        }
//        List<String> sqls = new ArrayList<>();
//        if (!table.getKey().equals(table.getTableName())) {
//            sqls.add(Strings.format("RENAME TABLE `{}`.`{}` TO `{}`.`{}`;", table.getCatalogName(),
//                    table.getKey(), table.getCatalogName(), table.getTableName()));
//        }
//        StringBuilder stringBuffer = new StringBuilder();
//        StringBuffer defaultModifySql = new StringBuffer();
//        if (!oldTable.getEngine().equals(table.getEngine())) {
//            stringBuffer.append(Strings.format(" ENGINE={} ", table.getEngine()));
//        }
//        if (!oldTable.getTableComment().equals(table.getTableComment())) {
//            stringBuffer.append(Strings.format(" COMMENT='{}' ", table.getTableComment()));
//        }
//        if (StringUtils.isNotBlank(table.getCharacter()) && !oldTable.getCharacter().equals(table.getCharacter())) {
//            defaultModifySql.append(Strings.format("  CHARSET={} ", table.getCharacter()));
//        }
//        if (StringUtils.isNotBlank(table.getCollation()) && !oldTable.getCollation().equals(table.getCollation())) {
//            defaultModifySql.append(Strings.format("  COLLATE={} ", table.getCollation()));
//        }
//        if (StringUtils.isNotBlank(table.getAutoIncrement()) && !oldTable.getAutoIncrement().equals(table.getAutoIncrement())) {
//            defaultModifySql.append(Strings.format("  AUTO_INCREMENT={} ", table.getAutoIncrement()));
//        }
//        if (StringUtils.isNotBlank(stringBuffer.toString())) {
//            sqls.add(Strings.format("ALTER TABLE `{}`.`{}` {} {}", table.getCatalogName(),
//                    table.getTableName(), stringBuffer.toString(), StringUtils.isBlank(defaultModifySql.toString()) ?
//                            "" : " DEFAULT " + defaultModifySql));
//        }
//        if (CollectionUtils.isNotEmpty(table.getFields())) {
//            for (Field field : table.getFields()) {
//                if (field.getAction() == null) {
//                    throw new JdbcMetaAnalysisException("解析更新表结构sql失败");
//                }
//                switch (field.getAction()) {
//                    case ADD:
//                        sqls.add(addField(field));
//                        break;
//                    case UPDATE:
//                        sqls.addAll(updateField(field));
//                        break;
//                    case DELETE:
//                        sqls.add(deleteField(field));
//                        break;
//                }
//            }
//        }
//        return sqls;
//    }
//
//    public String deleteField(Field field) {
//        return Strings.format(" alter table   `{}`.`{}`  drop column  `{}` ", field.getCatalogName(),
//                field.getTableName(), field.getColumnName());
//    }
//
//    public List<String> updateField(Field field) {
//        List<String> sqls = new ArrayList<>();
//        if (field.getDecimalDigits() == null) {
//            field.setDecimalDigits(0);
//        }
//        if (!field.getKey().equals(field.getColumnName())) {
//            String sql = " alter table  " + field.getCatalogName() + "." + field.getTableName() +
//                    " change ";
//            sql = sql + field.getKey() + " " + field.getColumnName() + " " + field.getSqlTypeName();
//            if (field.getSize() != null) {
//                sql = sql + " (" + field.getSize() + ")";
//            }
//            sqls.add(sql);
//
//        }
//        String sql2 = " alter table  " + field.getCatalogName() + "." + field.getTableName() +
//                " modify column " + field.getColumnName() + " " + field.getSqlTypeName();
//        if (field.getSize() != null) {
//            if (field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("float") || field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("double") ||
//                    field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("decimal")) {
//                sql2 = sql2 + " (" + field.getSize() + ", " +
//                        field.getDecimalDigits() + ")";
//            } else {
//                sql2 = sql2 + " (" + field.getSize() + ")";
//            }
//        }
//        sql2 = sql2 + " comment '" + field.getFieldComment() == null ? "" : field.getFieldComment() + "'";
//        sqls.add(sql2);
//        return sqls;
//    }
//
//    public String addField(Field field) {
//        if (field.getDecimalDigits() == null) {
//            field.setDecimalDigits(0);
//        }
//        String sql = " alter table `" + field.getCatalogName() + "." + field.getTableName()
//                + "` add column ";
//        sql = sql + field.getColumnName() + "  ";
//        sql = sql + field.getSqlTypeName();
//        if (field.getSize() != null) {
//            if (field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("float") || field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("double") ||
//                    field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("decimal")) {
//                sql = sql + " (" + field.getSize() + ", " +
//                        field.getDecimalDigits() + ")";
//            } else {
//                sql = sql + " (" + field.getSize() + ")";
//            }
//        }
//        sql = sql + " comment '" + field.getFieldComment() == null ? "" : field.getFieldComment() + "'";
//        return sql;
//    }
//
//    public String buildCreateTableSql(Table table) {
//        if (CollectionUtils.isEmpty(table.getFields())) {
//            throw new JdbcMetaAnalysisException("构建建表语句失败，至少添加一行字段信息");
//        }
//        String sql = "CREATE TABLE dep_db_1_1.uiui (\n" +
//                "\tColumn1 varchar(100) NULL,\n" +
//                "\tColumn2 varchar(100) DEFAULT 656 auto_increment NOT NULL COMMENT 'asdfasdf',\n" +
//                "\tCONSTRAINT uiui_PK PRIMARY KEY (Column2)\n" +
//                ")\n" +
//                "ENGINE=InnoDB\n" +
//                "DEFAULT CHARSET=utf8mb4\n" +
//                "COLLATE=utf8mb4_general_ci;";
//        StringBuffer sqlBuffer = new StringBuffer();
//        sqlBuffer.append(Strings.format(" CREATE TABLE  `{}`.`{}` (", table.getCatalogName(), table.getTableName()));
//        for (Field field : table.getFields()) {
//            if (field.getDecimalDigits() == null) {
//                field.setDecimalDigits(0);
//            }
//            sqlBuffer.append(Strings.format(" {} {}", field.getColumnName(), field.getSqlTypeName()));
//            if (field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("float") || field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("double") ||
//                    field.getSqlTypeName().toLowerCase(Locale.ROOT).equals("decimal")) {
//                sqlBuffer.append(Strings.format("({},{})", field.getSize(), field.getDecimalDigits()));
//            }
//            if (field.isAutoincrement()) {
//                sqlBuffer.append(" auto_increment ");
//            }
//            if (field.isNullable()) {
//                sqlBuffer.append(" NULL ");
//            } else {
//                sqlBuffer.append(" NOT  NULL ");
//            }
//            if (StringUtils.isNotBlank(field.getFieldComment())) {
//                sqlBuffer.append(Strings.format(" {} ", field.getFieldComment()));
//            }
//            sqlBuffer.append(",");
//        }
//        return "";
//    }
//
//    @Override
//    public List<String> buildIndexChangeSql(Index index) {
//        return null;
//    }

//
//    @Override
//    public List<String> getDataType() {
//        return Arrays.asList("TINYINT", "SMALLINT", "BINARY", "BIT", "TINYINT", "MONEY",
//                "DATETIME", "REAL", "DECIMAL", "IMAGE", "CHARACTER",
//                "MEDIUMINT", "INT", "INTEGER", "BIGINT", "FLOAT", "DOUBLE", "CHAR", "VARCHAR",
//                "TINYBLOB", "TINYTEXT", "BLOB", "TEXT", "MEDIUMBLOB", "MEDIUMTEXT", "LONGBLOB", "LONGTEXT",
//                "DATE", "TIME", "YEAR", "DATETIME", "TIMESTAMP");
//    }
}
